package cn.iocoder.yudao.module.trade.order.vo;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.framework.validation.ChineseName;
import cn.iocoder.yudao.framework.validation.PhoneNumber;
import cn.iocoder.yudao.module.api.trade.delivery.enums.DeliveryTypeEnum;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Nonnull;
import jakarta.validation.Valid;
import jakarta.validation.constraints.AssertTrue;
import lombok.Data;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;

@Tag(name = "用户 App - 交易订单结算 Request VO")
@Data
@Valid
@SuppressWarnings("DuplicatedCode")
public class AppTradeOrderSettlementReqVO {

    @Schema(description = "产品项数组")
    private Collection<Item> items;

    @Nonnull
    public Collection<Item> getItems() {
        if (items == null) {
            items = new ArrayList<>();
        }
        return items;
    }

    @Schema(description = "优惠劵编号", example = "0")
    private Long couponId;

    @Schema(description = "是否使用会员价", defaultValue = "false", example = "false")
    private Boolean useVipPrice;

    @Schema(description = "是否使用批发价", defaultValue = "false", example = "false")
    private Boolean useWholesalePrice;

    @Schema(description = "是否使用积分抵扣", defaultValue = "false", example = "false")
    private Boolean usePointDeduction;

    @Schema(description = "是否使用联盟豆抵扣", defaultValue = "false", example = "false")
    private Boolean useCryptocurrencyDeduction;

    @Schema(description = "是否联盟豆全额抵扣，来自云盟商城的产品需要全额抵扣", defaultValue = "false", example = "false")
    private Boolean fullCryptocurrencyDeduction;

    @Schema(description = "是否使用首单优惠", defaultValue = "false", example = "false")
    private Boolean useFirstOrderDiscount;

    @SuppressWarnings("unused")
    @AssertTrue(message = "会员价不能与其他优惠同时享受")
    @JsonIgnore
    public boolean validateVipPrice() {
        if (Boolean.TRUE.equals(useVipPrice)) {
            return !Boolean.TRUE.equals(useWholesalePrice)
                   && !Boolean.TRUE.equals(usePointDeduction)
                   && !Boolean.TRUE.equals(useCryptocurrencyDeduction)
                   && !Boolean.TRUE.equals(fullCryptocurrencyDeduction)
                   && !Boolean.TRUE.equals(useFirstOrderDiscount);
        }
        return true;
    }

    @SuppressWarnings("unused")
    @AssertTrue(message = "批发价不能与其他优惠同时享受")
    @JsonIgnore
    public boolean validateWholesalePrice() {
        if (Boolean.TRUE.equals(useWholesalePrice)) {
            return !Boolean.TRUE.equals(useVipPrice)
                   && !Boolean.TRUE.equals(usePointDeduction)
                   && !Boolean.TRUE.equals(useCryptocurrencyDeduction)
                   && !Boolean.TRUE.equals(fullCryptocurrencyDeduction)
                   && !Boolean.TRUE.equals(useFirstOrderDiscount);
        }
        return true;
    }

    @SuppressWarnings("unused")
    @AssertTrue(message = "积分抵扣不能与其他优惠同时享受")
    @JsonIgnore
    public boolean validatePointDeduction() {
        if (Boolean.TRUE.equals(usePointDeduction)) {
            return !Boolean.TRUE.equals(useVipPrice)
                   && !Boolean.TRUE.equals(useWholesalePrice)
                   && !Boolean.TRUE.equals(useCryptocurrencyDeduction)
                   && !Boolean.TRUE.equals(fullCryptocurrencyDeduction)
                   && !Boolean.TRUE.equals(useFirstOrderDiscount);
        }
        return true;
    }

    @SuppressWarnings("unused")
    @AssertTrue(message = "联盟豆抵扣不能与其他优惠同时享受")
    @JsonIgnore
    public boolean validateCryptocurrencyDeduction() {
        if (Boolean.TRUE.equals(useCryptocurrencyDeduction) || Boolean.TRUE.equals(fullCryptocurrencyDeduction)) {
            setUseCryptocurrencyDeduction(true);
            return !Boolean.TRUE.equals(useVipPrice)
                   && !Boolean.TRUE.equals(useWholesalePrice)
                   && !Boolean.TRUE.equals(usePointDeduction)
                   && !Boolean.TRUE.equals(useFirstOrderDiscount);
        }
        return true;
    }

    @SuppressWarnings("unused")
    @AssertTrue(message = "首单优惠不能与其他优惠同时享受")
    @JsonIgnore
    public boolean validateFirstOrderDiscountPrice() {
        if (Boolean.TRUE.equals(useFirstOrderDiscount)) {
            return !Boolean.TRUE.equals(useVipPrice)
                   && !Boolean.TRUE.equals(useWholesalePrice)
                   && !Boolean.TRUE.equals(usePointDeduction)
                   && !Boolean.TRUE.equals(useCryptocurrencyDeduction)
                   && !Boolean.TRUE.equals(fullCryptocurrencyDeduction);
        }
        return true;
    }

    // ========== 配送相关相关字段 ==========

    @Schema(description = "配送类型/服务方式：0-无、1-快递发货、2-到店自提、3-同城配送、4-现场核销、5-上门服务", example = "0")
    @InEnum(value = DeliveryTypeEnum.class, message = "配送类型/服务方式不正确")
    private Integer deliveryType;

    public Integer getDeliveryType() {
        if (deliveryType == null) {
            deliveryType = DeliveryTypeEnum.NONE.getType();
        }
        return deliveryType;
    }

    @Schema(description = "是否点餐模式", example = "false")
    private Boolean dineMode;

    @Schema(description = "上门服务地址或收货地址编号，上门服务及除了到店自提的配送类型/服务方式外都得提供", example = "0")
    private Long addressId;

    @Schema(description = "自提门店编号，选择到店自提时必须提供", example = "0")
    private Long pickUpStoreId;

    @Schema(description = "联系人名称，选择了上门服务地址或收货地址时无需传递", example = "羡民")
    @ChineseName
    private String contactName;

    @Schema(description = "联系人手机号，选择了上门服务地址或收货地址时无需传递", example = "15285116029")
    @PhoneNumber
    private String contactMobile;

    // ========== 秒杀活动相关字段 ==========
    @Schema(description = "秒杀活动编号，秒杀产品下单时提供", example = "0")
    private Long seckillActivityId;

    // ========== 拼团活动相关字段 ==========
    @Schema(description = "拼团活动编号，拼团产品下单时提供", example = "0")
    private Long combinationActivityId;

    @Schema(description = "拼团团长编号，拼团产品下单时提供", example = "0")
    private Long combinationHeadId;

    // ========== 砍价活动相关字段 ==========
    @Schema(description = "砍价记录编号，砍价产品下单时提供", example = "0")
    private Long bargainRecordId;

    // ========== 积分兑换活动相关字段 ==========
    @Schema(description = "积分兑换活动编号，积分产品下单时提供", example = "0")
    private Long pointActivityId;

    // ========== 团购活动相关字段 ==========
    @Schema(description = "团购套餐编号，团购套餐下单时提供", example = "0")
    private Long grouponPackageId;

    // ========== 点餐相关字段 ==========

    @Schema(description = "点餐餐桌编号，点餐下单时提供", example = "0")
    private Long dineDeskId;

    @Schema(description = "用餐人数，点餐下单时提供", example = "0")
    private Integer dinePeoples;

    @Schema(description = "预定日期，预约下单时提供")
    private LocalDate reserveDate;

    @Schema(description = "预定时间段，如12:00-12:30，预约下单时提供")
    private String reservePeriod;

    @SuppressWarnings("unused")
    @AssertTrue(message = "必须指定用餐人数")
    @JsonIgnore
    public boolean isValidDineDesk() {
        if (dineDeskId != null && dineDeskId > 0) {
            return dinePeoples != null && dinePeoples > 0;
        }
        return true;
    }

    @SuppressWarnings("unused")
    @AssertTrue(message = "参数错误：无法获取产品信息")
    @JsonIgnore
    public boolean isValidItems() {
        if (CollUtil.isNotEmpty(items)) {
            return true;
        }
        return grouponPackageId != null && grouponPackageId > 0;
    }

    @SuppressWarnings("unused")
    @AssertTrue(message = "活动产品每次只能购买一种规格")
    @JsonIgnore
    public boolean isValidActivityItems() {
        // 校验是否是活动订单
        if (ObjUtil.isAllEmpty(seckillActivityId, combinationActivityId, combinationHeadId, bargainRecordId, pointActivityId)) {
            return true;
        }
        // 校验订单项是否超出
        return items.size() == 1;
    }

    @Data
    @Schema(description = "用户 App - 商品项")
    @Valid
    public static class Item {

        @Schema(description = "产品 SKU 编号", example = "1")
        private Long skuId;

        @Schema(description = "购买数量", example = "1")
        private Integer count;

        @Schema(description = "购物车编号，从购物车下单时必须传", example = "0")
        private Long cartId;

        @SuppressWarnings("unused")
        @AssertTrue(message = "产品信息不正确")
        @JsonIgnore
        public boolean isValid() {
            // 组合一：skuId + count 使用产品 SKU
            if (skuId != null && skuId > 0 && count != null && count > 0) {
                return true;
            }
            // 组合二：cartId 使用购物车项
            return cartId != null && cartId > 0;
        }

    }

}
